<?php
class LtCookie
{
	public $configHandle;
	private $secretKey;

	public function __construct()
	{
		if (! $this->configHandle instanceof LtConfig)
		{
			$this->configHandle = LtObjectUtil::singleton("LtConfig");
		}
	}

	public function init()
	{ 
		$this->secretKey = $this->configHandle->get("cookie.secret_key");
		if(empty($this->secretKey))
		{
			trigger_error("cookie.secret_key empty");
		}
	}

	/**
	 * Decrypt the encrypted cookie
	 * 
	 * @param string $encryptedText 
	 * @return string 
	 */
	protected function decrypt($encryptedText)
	{
		$key = $this->secretKey;
		return $this->authcode($encryptedText,$key,'DECODE');
	}

	/**
	 * Encrypt the cookie
	 * 
	 * @param string $plainText 
	 * @return string 
	 */
	protected function encrypt($plainText)
	{
		$key = $this->secretKey;
		return $this->authcode($plainText,$key,'ENCODE');
	}
	
	private function authcode($string, $key, $operation = 'ENCODE')
	{
		$keyLength 	= strlen($key);
		if($keyLength == 0)
		{
			return false;
		}
		$string 		= $operation == 'DECODE' ? base64_decode($string) : substr(md5($string.$key), 0, 8).$string;
		$stringLength 	= strlen($string);
		
		$rndkey 		= $box = array();
		$result 		= '';
		
		for($i = 0; $i <= 255; $i++)
		{
			$rndkey[$i] 	= ord($key[$i % $keyLength]);
			$box[$i] 		= $i;
		}
		
		for($j = $i = 0; $i < 256; $i++)
		{
			$j 			= ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp 		= $box[$i];
			$box[$i] 	= $box[$j];
			$box[$j] 	= $tmp;
		}
		
		for($a = $j = $i = 0; $i < $stringLength; $i++)
		{
			$a 		= ($a + 1) % 256;
			$j 		= ($j + $box[$a]) % 256;
			$tmp 	= $box[$a];
			$box[$a] 	= $box[$j];
			$box[$j] 	= $tmp;
			$result 	.= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}
		
		if($operation == 'DECODE')
		{
			if(substr($result, 0, 8) == substr(md5(substr($result, 8).$key), 0, 8))
			{
				return substr($result, 8);
			}
			else
			{
				return '';
			}
		}
		else
		{
			return str_replace('=', '', base64_encode($result));
		}
	}
	
	/**
	 * Set cookie value to deleted with $name
	 * 
	 * @param array $args 
	 * @return boolean 
	 */
	public function delCookie($name, $path = '/', $domain = null)
	{
		if (isset($_COOKIE[$name]))
		{
			if (is_array($_COOKIE[$name]))
			{
				foreach($_COOKIE[$name] as $k => $v)
				{
					setcookie($name . '[' . $k . ']', '', time() - 86400, $path, $domain);
				}
			}
			else
			{
				setcookie($name, '', time() - 86400, $path, $domain);
			}
		}
	}

	/**
	 * Get cookie value with $name
	 * 
	 * @param string $name 
	 * @return mixed 
	 */
	public function getCookie($name)
	{
		$ret = null;
		if (isset($_COOKIE[$name]))
		{
			if (is_array($_COOKIE[$name]))
			{
				$ret = array();
				foreach($_COOKIE[$name] as $k => $v)
				{
					$v = $this->decrypt($v);
					$ret[$k] = $v;
				}
			}
			else
			{
				$ret = $this->decrypt($_COOKIE[$name]);
			}
		}
		return $ret;
	}

	/**
	 * Set cookie
	 * 
	 * @param array $args 
	 * @return boolean 
	 */
	public function setCookie($name, $value = '', $expire = null, $path = '/', $domain = null, $secure = 0)
	{
		if (is_array($value))
		{
			foreach($value as $k => $v)
			{
				$v = $this->encrypt($v);
				setcookie($name . '[' . $k . ']', $v, $expire, $path, $domain, $secure);
			}
		}
		else
		{
			$value = $this->encrypt($value);
			setcookie($name, $value, $expire, $path, $domain, $secure);
		}
	}
}
